//
//  asyncController.swift
//  DemoUI
//
//  Created by 白瑾浩 on 2022/2/14.
//

import UIKit

class asyncController: UIViewController {
    let lock = NSCondition()
    var count = 0    //生产者消费者模式
    let MAX_COUNT = 5   //仓库最多容量
    var thread1: Thread?   //特别提醒： 启动线程后要在适当时机释放！！！！！！
    var thread2: Thread?
    var dataArr:[Int] = []
    let NSMutableArray1: NSMutableArray = []
    let NSMutableArray2: NSMutableArray = []
    let mNSLock = NSLock()//代码块锁
    let mNSConditionLock = NSConditionLock() //条件锁
    let mNSRecursiveLock = NSRecursiveLock() //递归锁
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        //        Task {
        //            try await downloadImage(imageNumber: 1)
        //            let metadata = try await downloadMetadata(for: 1)
        //            let detailImage = DetailedImage(image: UIImage() )
        //            self.showImage(detailImage)
        //        }
        //        setupUI()
        //        doOtherThing()
        
        // Do any additional setup after loading the view.
        //        thread1 = Thread(target: self, selector: #selector(product(sender:)), object: nil)
        //        thread2 = Thread(target: self, selector: #selector(consume(sender:)), object: nil)
        //        thread1?.start()
        //        thread2?.start()     //跟Java一样用start方法启动线程
        //
        //创建一个子线程
        // Swift3.0
        //        DispatchQueue(label: "环城路").async {
        //            // 给碴土车走的（耗时操作）
        //            sleep( 1 )
        //            print( "环城路1" )
        //        }
        //        //全局队列
        //        // Swift3.0
        //        let qos: DispatchQoS.QoSClass =  .default
        //        // .userInitiated > .default > .utility > .background
        //
        //        DispatchQueue.global(qos:  qos).async {
        //            // 给碴土车走的（耗时操作）
        //            print( "环城路2" )
        //        }
        //
        //        // Swift3.0同步执行串行队列
        //        for i in 0..<3 {
        //            DispatchQueue(label: "syn.serial.queue").sync() {
        //                sleep( 1 )
        //                print("当前执行线程：\(Thread.current)")
        //                print("执行\(i)开始")
        //            }
        //            print("\(i)执行完毕")
        //        }
        //        //同步执行并行队列
        //        for i in 0..<3 {
        //            DispatchQueue(label: "syn.concurrent.queue", attributes: .concurrent).sync() {
        //                sleep( 1 )
        //                print("当前执行线程：\(Thread.current)")
        //                print("执行\(i)开始")
        //            }
        //            print("\(i)执行完毕")
        //        }
        //
        //        // Swift3.0 异步执行串行队列
        //        let group = DispatchGroup.init()
        //        let serialQueue = DispatchQueue(label: "serialQueue")
        //        for i in 0..<3 {
        //            group.enter()
        //            DispatchQueue(label: "asyn.serial.queue").async(group: group) {
        //                sleep( 1 )
        //                let currentThread = Thread.current
        //                serialQueue.sync {              //同步锁
        //                    group.leave()  //释放
        //                    print("①Sleep的线程\(currentThread)")
        //                    print("②当前输出内容的线程\(Thread.current)")
        //                    print("③执行\(i):\n")
        //                }
        //            }
        //            print("\(i)添加完毕\n")
        //        }
        //
        //
        //        // Swift3.0 异步执行并行队列
        //        let serialQueue2 = DispatchQueue(label: "serialQueue")
        //        for i in 0..<3 {
        //            group.enter()
        //            DispatchQueue(label: "asyn.concurrent.queue", attributes: .concurrent).async(group: group) {
        //                sleep(1)
        //                let currentThread = Thread.current
        //                serialQueue2.sync {              //同步锁
        //                    group.leave()
        //                    print("①Sleep的线程\(currentThread)")
        //                    print("②当前输出内容的线程\(Thread.current)")
        //                    print("③执行\(i):\n")
        //                }
        //            }
        //            print("\(i)添加完毕\n")
        //        }
        //        print("使用异步方式添加队列")
        //
        //        //延迟执行
        //
        //        // Swift3.0
        //        let time = 2
        //        let semaphore = DispatchSemaphore(value: 0)
        //        let queue = DispatchQueue.global()
        //        let delaySecond = DispatchTimeInterval.seconds(time)
        //
        //        print(Date())
        //        let delayTime = DispatchTime.now() + delaySecond
        //        queue.asyncAfter(deadline: delayTime) {
        //            print("执行线程：\(Thread.current)\ndispatch_time: 延迟\(time)秒执行\n",Date())
        //            semaphore.signal()
        //        }
        //
        //        //DispatchWallTime用于计算绝对时间,而DispatchWallTime是根据挂钟来计算的时间，即使设备睡眠了，他也不会睡眠。
        //        //        let nowInterval = Date().timeIntervalSince1970
        //        //        let nowStruct = timespec(tv_sec: Int(nowInterval), tv_nsec: 0)
        //        //        let delayWalltime = DispatchWallTime(timespec: nowStruct)
        //        let delayWalltime = DispatchWallTime.now() + delaySecond
        //        queue.asyncAfter(wallDeadline: delayWalltime) {
        //            print("执行线程：\(Thread.current)\ndispatch_walltime: 延迟\(time)秒执行\n", Date())
        //        }
        //        semaphore.wait()
        //
        //        print( "延迟执行完毕" )
        
        //moreThread()
        //moreThreadChuanxing()
        //moreThreadBingxing()
        //moreThreadBingxing3()
        //updateArrayData()
        //ios中的锁(Lock) NSLock，NSConditionLock，NSRecursiveLock，NSCondition
//        var number = 5
//        //用于访问和操作非类型化数据的原始指针。即对象类型的指针
//        let numberPointer = UnsafeMutableRawPointer(&number)
//        print( "numberPointer==\(numberPointer)" )
//        lockTest()
        
        var mRecordHistoryBean = RecordHistoryBean()
        
        print( mRecordHistoryBean.value )
        print( mRecordHistoryBean.name )
        
        
    }
    func setupUI(){
        print("初始化UI开始")
        sleep(1)
        print("初始化UI完成")
    }
    func doOtherThing(){
        print("其他事开始")
        print("其他事结束")
    }
    
    @MainActor
    func showImage(_ detailImage: DetailedImage){
        print("刷新UI")
        //self.imageButton.setImage(detailImage.image, for: .normal)
    }
    
    func downloadImage(imageNumber: Int) async throws -> Void {
        //            try Task.checkCancellation()
        //    //        if Task.isCancelled {
        //    //            throw ImageDownloadError.invalidMetadata
        //    //        }
        //            print("downloadImage----- begin \(Thread.current)")
        //            let imageUrl = URL(string: "http://r1on82fmy.hn-bkt.clouddn.com/await\(imageNumber).jpeg")!
        //            let imageRequest = URLRequest(url: imageUrl)
        //            let (data, imageResponse) = try await URLSession.shared.data(for: imageRequest)
        //            print("downloadImage----- end ")
        //            guard let image = UIImage(data: data), (imageResponse as? HTTPURLResponse)?.statusCode == 200 else {
        //                throw ImageDownloadError.badImage
        //            }
        //                return image
    }
    func downloadMetadata(for id: Int) async throws -> Void { //ImageMetadata {
        try Task.checkCancellation()
        //        if Task.isCancelled {
        //            throw ImageDownloadError.invalidMetadata
        //        }\
        //        print("downloadMetadata --- begin \(Thread.current)")
        //        let metadataUrl = URL(string: "http://r1ongpxur.hn-bkt.clouddn.com/imagemeta\(id).json")!
        //        let metadataRequest = URLRequest(url: metadataUrl)
        //        let (data, metadataResponse) = try await URLSession.shared.data(for: metadataRequest)
        //        print("downloadMetadata --- end  \(Thread.current)")
        //        guard (metadataResponse as? HTTPURLResponse)?.statusCode == 200 else {
        //            throw ImageDownloadError.invalidMetadata
        //        }
        //        return try JSONDecoder().decode(ImageMetadata.self, from: data)
    }
    
    struct ImageMetadata: Codable {
            let name: String
            let firstAppearance: String
            let year: Int
    }
    
    struct DetailedImage {
            let image: UIImage
           // let metadata: ImageMetadata
    }
    
    enum ImageDownloadError: Error {
            case badImage
            case invalidMetadata
    }
    
    
}
extension asyncController{
    
    @objc func product(sender: AnyObject) {
        repeat {
            //在线程执行体添加判断
            if let cancelled = thread1?.isCancelled, cancelled {
                print("真正关闭线程1")
                return   //调用cancel方法后， 退出线程执行体； 作用同Java的Thread一样
            }
            self.lock.lock()
            defer {
                self.lock.signal()
                self.lock.unlock()
                
            }
            if count == MAX_COUNT {
                print("仓库已满了， 等待消费.......")
                lock.wait()
            }
            
            count += 1
            print("生产1个商品，当前总数:\(count)")
            
            lock.signal()    //只激活一个等待lock的线程， 而broadcast是激活所有等待lock的线程
            lock.unlock()
        } while true
    }
    
    @objc func consume(sender: AnyObject) -> Void {
        while true {
            if let cancelled = thread2?.isCancelled, cancelled {
                print("真正关闭线程2")
                return   //调用cancel方法后， 退出线程执行体； 作用同Java的Thread一样
            }
            
            lock.lock()
            //Thread.sleep(forTimeInterval: 0.1)   //睡0.1秒
            
            if count == 0 {
                print("没有商品了，等待生产。。。。。。")
                lock.wait()   //没有商品了， 等待商品
            }
            count -= 1
            print("消费1个商品，当前总数:\(count)")
            
            lock.signal()
            lock.unlock()
        }
        
    }
    //并行
    func moreThread(){
        //        let workItem = DispatchWorkItem {
        //                    print("开始干活\(Thread.current)")
        //                }
        //        workItem.perform() //立即执行, 放到了当前main队列中
        //        DispatchQueue.global().async(execute: workItem) //放到global队列中
        let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->1")
            queue.async(execute: {
                sleep( 2 )
                print("当前线程\(Thread.current)------->2")
            })
            queue.async(execute: {
                print("当前线程\(Thread.current)------->3")
            })
        })
        //Z这里不会等待队列执行完成就执行
        let workItem = DispatchWorkItem {
            print("done")
        }
        group.notify(queue: queue, work: workItem)
        
    }
    //b并行2
    func moreThreadBingxing(){
        let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue3", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->111")
        })
        queue.async(group: group, execute: {
            sleep( 2 )
            print("当前线程\(Thread.current)------->222")
        })
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->333")
        })
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->444")
        })
        let workItem = DispatchWorkItem {
            print("执行完成000")
        }
        group.notify(queue: queue, work: workItem)
    }
    // 延续 moreThread 的  等待执行完成才执行 workitem
    func moreThreadBingxing3(){
        let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->1")
            group.enter() //加入
            queue.async(execute: {
                sleep( 2 )
                print("当前线程\(Thread.current)------->2")
                group.leave() //释放
            })
            group.enter()
            queue.async(execute: {
                print("当前线程\(Thread.current)------->3")
                group.leave()
            })
        })
        let workItem = DispatchWorkItem {
            print("done======")
        }
        group.notify(queue: queue, work: workItem)
    }
    
    //串行
    func moreThreadChuanxing(){
        let queue = DispatchQueue(label: "myQueue2", qos: DispatchQoS.default )
        queue.async {
            print("当前线程\(Thread.current)------->11")
        }
        //这里要等待2执行完成 才进行下一步
        queue.async {
            sleep( 2 )
            print("当前线程\(Thread.current)------->22")
        }
        queue.async {
            print("当前线程\(Thread.current)------->33")
        }
        queue.async {
            print("当前线程\(Thread.current)------->44")
            DispatchQueue.main.async {
                print("执行完了")
            }
        }

        
    }
    func updateArrayData(){
        
        var array: [Int] = []
        //异步插入会出现访问同一内存地址 会报错并发问题
        //        for i in 0...100 {
        //            DispatchQueue.global().async(execute: {
        //                array.append(i)
        //            })
        //        }
        //第一种  同步插入 串行执行
        //        for i in 0...100 {
        //            DispatchQueue.global().sync(execute: {
        //                array.append(i)
        //            })
        //        }
        
        //第二种  信号量解决问题
        //        let semaphore = DispatchSemaphore(value: 1)
        //        for i in 0...100 {
        //            DispatchQueue.global().async(execute: {
        //                /*
        //                 wait 等待信号量semaphore >= 1时执行
        //                 wait返回时 semaphore 减1
        //                 */
        //                _ = semaphore.wait(wallTimeout: .distantFuture)
        //                array.append(i) //只会同时被一个线程访问
        //                /*
        //                 signal semaphore 加1
        //                 */
        //                semaphore.signal()
        //            })
        //        }
        //
        //第三种  互斥锁 解决并发问题
//        let lock = NSLock()
//        for i in 0...100 {
//            DispatchQueue.global().async(execute: {
//                lock.lock()
//                array.append(i)
//                lock.unlock()
//            })
//        }
        
        
        
        DispatchQueue.main.async {
            print("总的条数：\(array.count)")
        }
        print( "完成插入" )

    }
    
}

extension asyncController{
    //锁的条件实例的使用

    func lockTest(){
        //代码块锁
//        let thread1 = Thread(target: self, selector: #selector(product1(sender:)), object: nil)
//        thread1.start()
//        let thread2 = Thread(target: self, selector: #selector(product2(sender:)), object: nil)
//        thread2.start()
        //条件锁
//        let thread3 = Thread(target: self, selector: #selector(product3(sender:)), object: nil)
//        thread3.start()
//        let thread4 = Thread(target: self, selector: #selector(product4(sender:)), object: nil)
//        thread4.start()
        //递归锁
        let thread5 = Thread(target: self, selector: #selector(product5(sender:)), object: nil)
        thread5.start()
        
    }
    @objc func product1(sender: AnyObject){
        mNSLock.lock()
        for i in 0..<5{
            sleep(1)
           // dataArr.append( i )
            NSMutableArray1.add( "a\(i)" )
        }
        print( NSMutableArray1 )
        mNSLock.unlock()
    }
    @objc  func product2(sender: AnyObject){
        mNSLock.lock()
        for i in 0..<5{
            sleep(1)
           // dataArr.append( i )
            NSMutableArray1.add( "b\(i)" )
        }
        
        print( NSMutableArray1 )
        mNSLock.unlock()
    }
    @objc func product3(sender: AnyObject){
        
        for i in 0..<10{
            mNSConditionLock.lock()
            mNSConditionLock.unlock(withCondition: i)
            print( "i=\(i)" )
            sleep(1)
        }
    }
    @objc func product4(sender: AnyObject){
        print( "================上锁开始" )
        mNSConditionLock.lock(whenCondition: 3)
        print( "================上锁成功" )
        sleep(5)
        print( "================执行完成" )
        mNSConditionLock.unlock()
        print( "================解锁" )
    }
    //递归锁回调
    @objc func product5(sender: AnyObject){
        subTotal( 20 );
    }
    func subTotal(_ value:Int ){
        mNSRecursiveLock.lock()
        var valueNew = value
        if valueNew > 0 {
            valueNew = valueNew - 1
            print( valueNew )
            subTotal( valueNew )
        }
        mNSRecursiveLock.unlock()
    }
    
}

class RecordHistoryBean{
    var value:Int!
    var name:String!
}
